package
{
	import away3d.animators.*;
	import away3d.containers.*;
	import away3d.entities.Sprite3D;
	
	import engine.asset.*;
	import engine.core.*;
	import engine.graphics.*;
	import engine.graphics.anim.*;
	import engine.graphics.away3d.*;
	import engine.graphics.lighting.*;
	import engine.graphics.shader.*;
	import engine.graphics.sprite.*;
	import engine.graphics.vfx.*;
	import engine.loaders.*;
	import engine.math.*;
	import engine.network.*;
	import engine.profile.*;
	import engine.social.*;
	import engine.sound.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.net.*;
	import flash.system.*;
	import flash.utils.*;
	
	import game.*;
	import game.actor.*;
	import game.asset.*;
	import game.core.*;
	import game.graphics.*;
	import game.graphics.away3d.*;
	import game.graphics.lighting.*;
	import game.messages.*;
	import game.messages.login.*;
	import game.network.*;
	import game.scene.*;
	import game.sound.*; 
	import game.store.*;
	import game.telemetry.*;
	import game.ui.controls.*;
	import game.ui.core.*;
	import game.ui.hud.*;
	import game.ui.script.*;
	
	public class RxMain extends Sprite
	{
		public static const GAME_STATE_LOADING:uint = 1;
		public static const GAME_STATE_WAITING_FOR_LOADS:uint = 2;
		public static const GAME_STATE_RENDERING:uint = 3;
		
		private static var s_isAutomated:Boolean = false;
		private static var s_automatedRender:Boolean = false;
		public static var instance:RxMain;
		private static var s_automatedWebClient:RxWebClient = null;
		private static var s_automatedWebBusy:Boolean = false;
		private static var s_automatedRequest:Array = new Array();
		private static var s_automatedId:String = "";
		
		private var m_assetsPath:String;
		private var m_ssPort:int;
		private var m_ssURL:String;
		private var m_staticManifestFile:String;
		private var m_staticAssetsPath:String;
		private var m_platformURL:String;
		private var m_gameID:String;
		private var m_landingURL:String;
		private var m_view:View3D;
		private var m_scene:RxScene;
		private var m_camera:RxCamera3D;
		private var m_renderer:RxRenderer;
		private var m_gameCamera:RxGameCamera;
		private var m_lastStepTime:Number = 0;
		private var m_worker:RxTimerWorker;
		private var m_profilerState:RxProfilerState;
		private var m_samplingProfiler:RxSamplingProfiler;
		private var m_frameDualProfiler:RxDualProfiler;
		private var m_accumDualProfiler:RxDualProfiler;
		private var m_lastFreeMemory:Number;
		private var m_lastTotalMemory:Number;
		private var m_screenCaptureBitmap:Bitmap;
		private var m_screenCaptureMask:uint;
		private var m_gameState:uint;
		private var m_loadTimer:Timer;
		
		// change for yzb
		private var m_gameCommandConsole:RxGameCommandConsole;
		private var m_social:RxSocial;
		private var m_partyManager:RxPartyManager;
		private var m_netIDManager:RxNetIDManager;
		private var m_transactionServer:RxTransactionServer;
		private var m_gamedata:RxGameData;
		private var m_store:RxStore;
		
		public function RxMain()
		{
			instance = this;
			Security.allowDomain("String");
			Security.allowInsecureDomain("String");
			
			this.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
		}
		
		private function addedToStage(e:Event) : void
		{
			RxStage.stage = this.stage;
			this.stage.frameRate = 60;
			this.stage.color = 4279704358;
			this.stage.quality = StageQuality.HIGH;
			this.stage.scaleMode = StageScaleMode.NO_SCALE;
			this.stage.align = StageAlign.TOP_LEFT;
			
			stage.addEventListener(Event.RESIZE, this.OnStageResize);
			
			Security.allowDomain("*");
			Security.allowInsecureDomain("*");
			
			m_profilerState = new RxProfilerState(stage, "Courier");
			m_samplingProfiler = m_profilerState.GetSamplingProfiler();
			m_frameDualProfiler = m_profilerState.GetFrameDualProfiler();
			m_accumDualProfiler = m_profilerState.GetAccumDualProfiler();
			
			loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, RxClientError.OnUncaughtError);
		
			m_assetsPath = this.loaderInfo.parameters["assetsPath"];
			m_ssPort = this.loaderInfo.parameters["ssPort"];
			m_ssURL = this.loaderInfo.parameters["ssUrl"];
			m_staticManifestFile = this.loaderInfo.parameters["staticManifestFile"] || "assets/blob_manifest.txt";//"https://d15tpfs79gp3yw.cloudfront.net/valor/v479__416d249464d363653c1b0fd440dbae426071cd49/blob_manifest.txt";
			m_staticAssetsPath = this.loaderInfo.parameters["staticAssetsPath"] || "https://d15tpfs79gp3yw.cloudfront.net/valor/blobcontent3/";
			this.m_platformURL = this.loaderInfo.parameters["platform_url"] || "https://dep620.rumblegames.com/cdreplat1/";
			this.m_gameID = this.loaderInfo.parameters["game_gukey"] || "4407e9bd675f17bc11e9d7f8f7002e89";
			this.m_landingURL = this.loaderInfo.parameters["landing_url"] || "http://localhost:5000/cdreplat1/grails/valorLaunch/rg.dispatch?isSecure=true";
			if (m_assetsPath == null)
			{
				//m_assetsPath = "assets/";
				m_assetsPath = "https://d15tpfs79gp3yw.cloudfront.net/valor/v479__416d249464d363653c1b0fd440dbae426071cd49/assets/";
			}
			if (m_ssURL == null)
			{
				//m_ssURL = "localhost";
				m_ssURL = "itvm622.rumblegames.com";
			}
			if (m_ssPort == 0)
			{
				m_ssPort = 9001;
			}
			
			RxManifest.SetPaths(m_staticManifestFile, m_staticAssetsPath);
			RxLog.AddListener(RxExternalInterface.LogListener, RxLog.INFO);
			RxPlatform.Initialize(this.m_platformURL, this.m_gameID);
			m_gameCommandConsole = new RxGameCommandConsole("Courier", stage);
			RxLog.AddListener(RxCommandConsole.instance.LogListener, RxLog.DEBUG);
			
			var jiraURL:String = "https://jira-community.rumblegames.com";
			var jiraUser:String = "kingsroad.client";
			var jiraPassword:String = "k50795-y";
			var jiraKey:String = "KRC";
			RxJiraClient.Initialize(
				"KingsRoad", jiraURL, jiraUser, jiraPassword, jiraKey,
				function () : String
				{
					var sysInfo:String = RxSystemInfo.Write(RxStage.stage);
					var gameInfo:String = RxGameInfo.Write();
					var command:String = RxCommandConsole.instance.GetText();
					return (sysInfo + gameInfo + command);
				});
			
			var startDate:Date = new Date();
			var startTime:Number = startDate.getTime();
			startTime = startTime - getTimer();
			startDate.setTime(startTime);
			var dateString:String = RxUtilities.ConvertToReadableUTCDate(startDate);
			
			RxLog.Info("Flash VM Start Time: " + dateString + " UTC");
			
			this.m_lastFreeMemory = System.freeMemory;
			this.m_lastTotalMemory = System.totalMemoryNumber;
			
			this.m_accumDualProfiler.Start("system Init");
			this.m_worker = new RxTimerWorker(60, 4);
			RxMatrix4x4.CreatePool(128, 128);
			RxPlane.CreatePool(128, 128);
			RxQuaternion.CreatePool(128, 128);
			RxVector4.CreatePool(128, 128);
			RxRotTrans.CreatePool(128, 128);
			RxWorldMeshFX.CreatePool(128, 128);
			RxWorldSpriteFX.CreatePool(128, 128);
			RxWorldQuadMeshFX.CreatePool(128, 128);
			RxWorldParticleFX.CreatePool(128, 128);
			RxWorldLightFX.CreatePool(128, 128);
			RxAnimatedParamScalar.CreatePool(512, 512);
			RxAnimatedParamUVTransform.CreatePool(512, 512);
			RxAnimatedParamVector4.CreatePool(512, 512);
			RxSprite3D.CreatePool(128, 128);
			RxAnimSprite3D.CreatePool(128, 128);
			RxAnimTextureSheet.CreatePool(128, 128);
			RxEntity.Initialize(RxEntityPhase.ENTITY_PHASE_NAMES, RxEntityType.ENTITY_TYPE_NAMES);
			RxActor.Initialize(RxEntityType.ENTITY_TYPE_NAMES.length);
			RxLoader.Initialize(this.m_assetsPath);
			
			RxAsset.Initialize(this.m_worker);
			RxAssetGroup.Initialize();
			RxAssetShader.Initialize();
			RxAssetImage.Initialize();
			RxAssetModel.Initialize();
			RxAssetCharacter.Initialize();
			RxAssetScene.Initialize();
			RxAssetAnimation.Initialize();
			RxAssetSound.Initialize();
			RxAssetSpriteSheet.Initialize();
			RxAssetSWF.Initialize();
			RxAssetXML.Initialize();
			RxAssetCSV.Initialize();
			RxAssetVFX.Initialize();
			RxAssetNavNode.Initialize();
			RxAssetMapInfo.Initialize();
			RxAssetLayout.Initialize();
			
			RxDragManager.Initialize();
			RxSoundManager.Initialize(64000);			
			RxLoader3D.SetWorker(this.m_worker);
			this.m_screenCaptureBitmap = new Bitmap(null);
			this.m_screenCaptureMask = 0;
			this.m_gameState = GAME_STATE_LOADING;
			this.m_accumDualProfiler.End();
			
			this.m_accumDualProfiler.Start("network Init");
			RxRegisterAllMessages.Register();
			m_social = new RxSocial();
			m_partyManager = new RxPartyManager();
			m_netIDManager = new RxNetIDManager();
			m_transactionServer = new RxTransactionServer(m_ssURL, m_ssPort, new RxNetMessageDistributor());
			
			RxServerLog.Reset();
			
			m_gamedata = new RxGameData(RxTransactionServer.instance);
			RxSimulation.Initialize(RxTransactionServer.instance);
			RxJoin.Initialize(RxTransactionServer.instance);
			RxServerVars.Initialize(RxTransactionServer.instance);
			m_store = new RxStore();
			this.m_accumDualProfiler.End();
			
			RxExternalInterface.Initialize();
			
			this.m_accumDualProfiler.Start("render Init");
			var OrthographicLens:RxOrthographicLens = new RxOrthographicLens(1, 1, true);
			this.m_camera = new RxCamera3D(OrthographicLens);
			this.m_renderer = new RxRenderer(this.m_camera, this.m_worker, this.m_frameDualProfiler);
			this.m_scene = new RxScene(this.m_camera);
			// change for yzb
			this.m_view = new View3D(null, this.m_camera, this.m_renderer);
			//this.m_view.SetScene(this.m_scene);
			this.m_gameCamera = new RxGameCamera(this.m_view, "camera");
			this.addChild(this.m_view);
			RxAssetModel.SetShaderFamilyManager(this.m_renderer.GetShaderFamilyManager());
			this.m_accumDualProfiler.End();
			
			this.m_accumDualProfiler.Start("UI Init");
			RxUI.Initialize(stage, this.m_view);
			this.m_accumDualProfiler.End();
			
			RxKeyboard.Initialize(stage);
			RxMouse.Initialize(this.m_view.hitField, stage);
			RxUtilities.ForceGarbageCollection();
			
			this.m_accumDualProfiler.Start("BootGame");
			RxMaster.Initialize(stage, this.m_view, this.m_gameCamera);
			RxMaster.SetProfilerState(this.m_profilerState);
			RxMaster.BootGame();
			this.m_accumDualProfiler.End();
			
			RxTick.Initialize();
			addEventListener(Event.ENTER_FRAME, this.EnterFrame);
			StartLoadTimer();
		}
		
		private function StartLoadTimer() : void
		{
			this.StopLoadTimer();
			this.m_loadTimer = new Timer(2 * 60 * 1000);
			this.m_loadTimer.addEventListener(TimerEvent.TIMER, this.OnLoadTimeout);
			this.m_loadTimer.start();
		}
		
		private function StopLoadTimer() : void
		{
			if (this.m_loadTimer != null)
			{
				this.m_loadTimer.stop();
				this.m_loadTimer.removeEventListener(TimerEvent.TIMER, this.OnLoadTimeout);
				this.m_loadTimer = null;
			}
		}
		
		private function OnLoadTimeout(event:TimerEvent) : void
		{
			this.StopLoadTimer();
			RxClientError.OnLoadTimeout();
		}
		
		private function EnterFrame(event:Event) : void
		{
			var arr:Array = [];
			var texture:RxVirtualTexture = null;
			
			RxContext.Push("RxMain.EnterFrame");
			
			if (this.m_renderer.CheckForLostDevice())
			{
				arr = ["Refresh"];
				RxDialogManager.instance.ShowAlert("Graphics Hardware Reset", "The graphics hardware was reset.  Please hit the refresh button to reload the game", arr, 0, null, OnLostDeviceAlertClosed, false, true, true);
				StopUpdate();
			}
			else
			{	
				this.m_frameDualProfiler.Start("mainLoop");
				
				if (this.m_gameState == GAME_STATE_WAITING_FOR_LOADS)
				{
					if (this.m_gameCamera.GetTarget() != null || RxClientVars.GetInt("layoutEditor") == 1)
					{
						texture = this.m_renderer.GetVirtualTexture();
						if (texture != null)
						{
							if (VirtualTextureRegionsLoaded())
							{
								RxPerformanceTelemetry.SetMode(RxPerformanceTelemetry.MODE_PLAYING_MAP);
								this.SetGameState(GAME_STATE_RENDERING);
							}
							else
							{
								this.m_renderer.LoadGigaTexture();
							}
						}
					}
				}
				
				this.UpdateFrame();
				
				if (this.m_gameState == GAME_STATE_RENDERING)
				{
					this.RenderFrame();
				}
				
				RxKeyboard.Reset();
				RxMouse.Reset();
				this.m_frameDualProfiler.End();
				this.m_frameDualProfiler.End();
				this.m_profilerState.UpdateTextFields(this.m_renderer, this.m_scene);
				this.m_frameDualProfiler.Start("frame");
				this.m_lastFreeMemory = System.freeMemory;
				this.m_lastTotalMemory = System.totalMemoryNumber;
			}
			
			RxContext.Pop();
		}
		
		public function StopUpdate() : void
		{
			removeEventListener(Event.ENTER_FRAME, this.EnterFrame);
		}
		
		public function VirtualTextureRegionsLoaded() : Boolean
		{
			var texture:RxVirtualTexture = this.m_renderer != null ? (this.m_renderer.GetVirtualTexture()) : (null);
			if (texture != null)
			{
				return texture.IsMappedRegionLoaded(RxGigaTextureInfo.TEXTURE_TYPE_COLOR) && texture.IsMappedRegionLoaded(RxGigaTextureInfo.TEXTURE_TYPE_DEPTH);
			}
			
			return false;
		}
		
		private function RenderFrame() : void
		{
			if (this.m_view.width != 0 && this.m_view.height != 0)
			{
				RxEntity.DebugDisplay(this, 200, 200);
				if (!s_isAutomated || s_automatedRender)
				{
					if (this.m_screenCaptureMask)
					{
						this.RenderAndCaptureFrame();
					}
					else
					{
						this.m_renderer.Clear();
						this.m_renderer.RenderScene(this.m_scene);
						this.m_renderer.Present();
					}
				}
			}
		}
		
		private function RenderAndCaptureFrame() : void
		{
			this.m_renderer.Clear();
			this.m_renderer.RenderScene(this.m_scene);
			if (this.m_screenCaptureBitmap.bitmapData == null)
			{
				this.m_screenCaptureBitmap.bitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0);
			}
			if (this.m_screenCaptureMask & 1)
			{
				this.m_view.stage3DProxy.context3D.drawToBitmapData(this.m_screenCaptureBitmap.bitmapData);
			}
			this.m_renderer.Present();
			if (this.m_screenCaptureMask & 2)
			{
				this.m_screenCaptureBitmap.bitmapData.draw(stage);
			}
			this.m_screenCaptureMask = 0;
		}
		
		private function UpdateFrame() : void
		{
			var entitys:Vector.<RxEntity> = null;
			var count:int = 0;
			this.m_frameDualProfiler.Start("update");
			RxTick.Update();
			RxPerformanceTelemetry.Update();
			var frameTime:Number = RxTick.frameTime;
			
			if (frameTime != 0)
			{
				RxActorState.PathRequestUpdate();
				RxActorState.s_targetPathTime = 0;
				RxSimulation.Update(frameTime, this.m_view, this.m_gameCamera);
				RxTransactionServer.instance.Update(frameTime);
				RxJoin.Update(this.m_view, this.m_gameCamera);
				RxMusicManager.Update();
				RxRecord.UpdateForRecord(frameTime);
				entitys = RxEntity.FindByPhase("npc");
				count = entitys != null ? (entitys.length) : (0);
				this.m_frameDualProfiler.Start("entity (" + count + ")");
				RxEntity.UpdateAll(frameTime);
				this.m_frameDualProfiler.End();
				RxUI.UpdateAll(frameTime);
				
				if (this.m_gameState == GAME_STATE_RENDERING)
				{
					RxActorState.AdjustDisplayPositions();
					
					if (!s_isAutomated || s_automatedRender)
					{
						AnimatorBase.s_numAnimators = 0;
						this.m_frameDualProfiler.Start("render");
						this.m_renderer.Update(frameTime, this.m_scene);
						this.m_frameDualProfiler.End();
					}
					
					RxEntity.UpdateActorAttachments(frameTime);
					this.m_frameDualProfiler.Start("mouse (" + RxBound.GetNumBounds() + ")");
					RxBound.Update(this.m_view, this);
					this.m_frameDualProfiler.End();
				}
				
				this.m_frameDualProfiler.End();
			}
		}
		
		
		
		public function SetGameState(gameState:uint) : void
		{
			RxContext.Push("RxMain.SetGameState", gameState);
			RxContext.SetGlobal("gameState", gameState.toString());
			
			this.m_gameState = gameState;
			switch(this.m_gameState)
			{
				case GAME_STATE_LOADING:
				{
					RxAsset.LoadRequestsImmediate(true);
					RxRUMParser.PostLoad(false);
					this.m_worker.SetAsynchronous(false);
					this.m_gameCamera.SetTarget(null);
					RxUI.OnChangingMap();
					RxLog.Info("GameState = loading (sending load requests)");
					break;
				}
				case GAME_STATE_WAITING_FOR_LOADS:
				{
					RxAsset.LoadRequestsImmediate(false);
					this.m_worker.SetAsynchronous(false);
					RxLog.Info("GameState = waiting for loads (waiting for the final load completions)");
					break;
				}
				case GAME_STATE_RENDERING:
				{
					RxUI.OnGameLoadComplete();
					RxRUMParser.PostLoad(true);
					this.m_worker.SetAsynchronous(true);
					RxLog.Info("GameState = rendering (primary loads completed, so we can render)");
					break;
				}
				default:
				{
					RxLog.Error("Invalid game state specified: " + gameState);
					break;
				}
			}
			
			RxContext.Pop();
		}
		
		public function OnGameShownToUser() : void
		{
			this.StopLoadTimer();
			RxClientError.OnGameShownToUser();
		}
		
		public function OnLoadProgress() : void
		{
			if (!RxClientError.HasGameBeenShownToUser())
			{
				this.StartLoadTimer();
			}
		}
		
		private static function OnLostDeviceAlertClosed(alert:RxAlert, info:String) : void
		{
			RxExternalInterface.RefreshBrowser();
		}
		
		private function OnStageResize(event:Event) : void
		{
			RxContext.Push("RxMain.OnStageResize");
			
			if (m_view != null)
			{
				m_view.width = stage.stageWidth;
				m_view.height = stage.stageHeight;
			}
			
			if (m_view.width > 0 && m_view.height > 0)
			{
				m_renderer.ResizeBackbuffer(m_view.width, m_view.height);
			}
			
			if (m_screenCaptureBitmap.bitmapData != null)
			{
				m_screenCaptureBitmap.bitmapData.dispose();
				m_screenCaptureBitmap.bitmapData = null;
			}
			
			RxContext.Pop();
		}
		
		public function GetClientInfo() : RxLogin_ClientInfo
		{
			var clientInfo:RxLogin_ClientInfo = new RxLogin_ClientInfo();
			var collectInfo:Object = RxSystemInfo.Collect(RxStage.stage);
			clientInfo.device = "FlashPlayer";
			clientInfo.os = collectInfo.os + (collectInfo.os64Bit ? (" (64 bit)") : (""));
			clientInfo.systemLanguage = collectInfo.language;
			clientInfo.browserName = collectInfo.browserType;
			clientInfo.browserVersion = collectInfo.browserVersion;
			clientInfo.socialNetwork = RxTransactionServer.instance.GetLoginChannel();
			clientInfo.socialNetworkUserId = RxTransactionServer.instance.GetLoginUserId();
			clientInfo.graphicsDriverType = collectInfo.graphicsDriver;
			clientInfo.flashVersion = collectInfo.playerVersion;
			clientInfo.flashType = collectInfo.playerConfiguration + " " + collectInfo.playerType;
			clientInfo.screenWidth = collectInfo.screenResolutionX;
			clientInfo.screenHeight = collectInfo.screenResolutionY;
			clientInfo.landingUrl = this.m_landingURL;
			
			return clientInfo;
		}
		
		public static function SetAutomated() : void
		{
			s_isAutomated = true;
			RxStage.stage.frameRate = 10;
			var localhost:String = "localhost";
			if (RxClientVars.StringExists("automatedLogger"))
			{
				localhost = RxClientVars.GetString("automatedLogger");
			}
			if (RxClientVars.IntExists("automatedRender" + RxExternalInterface.GetBrowser()))
			{
				s_automatedRender = RxClientVars.GetInt("automatedRender" + RxExternalInterface.GetBrowser()) != 0;
			}
			else if (RxClientVars.IntExists("automatedRender"))
			{
				s_automatedRender = RxClientVars.GetInt("automatedRender") != 0;
			}
			s_automatedId = RxClientVars.GetString("loginId");
			s_automatedWebClient = new RxWebClient("http://" + localhost + ":" + 8088);
			RxLog.AddListener(RxMain.AutomatedLogListener, RxLog.DEBUG);
			new RxAutomated();
			RxMain.instance.m_renderer.GetWorldFXManager().Enable(s_automatedRender);
		}
		
		private static function AutomatedLogListener(level:int, message:String, timestamp:String, callstack:String, force:Boolean) : void
		{
			var callback:Function;
			var logEntry:URLVariables = new URLVariables();
			logEntry.id = s_automatedId;
			logEntry.level = RxLog.GetLevelString(level);
			logEntry.message = message;
			if (s_automatedWebBusy)
			{
				s_automatedRequest.push(logEntry);
			}
			else
			{
				callback = function (param1:int, param2:ByteArray) : void
				{
					var _loc_3:URLVariables = null;
					if (s_automatedRequest.length > 0)
					{
						_loc_3 = s_automatedRequest.shift();
						s_automatedWebClient.PostURLVariables("/logger", _loc_3, callback);
					}
					else
					{
						s_automatedWebBusy = false;
					}
					return;
				};
				
				s_automatedWebBusy = true;
				s_automatedWebClient.PostURLVariables("/logger", logEntry, callback);
			}
		}
		
		public static function IsAutomated() : Boolean
		{
			return s_isAutomated;
		}
		
		public function SetScreenCaptureMask(mask:uint) : void
		{
			this.m_screenCaptureMask = mask;
		}
		
		public function GetScreenCaptureBitmap() : Bitmap
		{
			return this.m_screenCaptureBitmap;
		}
		
		public function GetWorker() : RxTimerWorker
		{
			return this.m_worker;
		}
	}
}